package com.zombies.list.linkedlist.singlecirclelinkedlist;

import com.zombies.list.adt.MyList;

/**
 *  单项循环链表实现
 *  约定：头节点就是第一个数据存储节点,没有空节点
 *
 * @author zombies
 * @create 2022-04-20 11:21
 */
public class MySingleCircleLinkedList<E> implements MyList<E> {

    private Node<E> head;

    public MySingleCircleLinkedList() {
        head = new Node<E>(null,null);
        head.next = head;
    }

    private static class  Node<E>{

        public Node( Node<E> next,E data) {
            this.data = data;
            this.next = next;
        }

        E data;
        Node<E> next;
    }


    /**
     * 查看线性表是否为空
     *
     * @return 为空返回true 反之false
     */
    @Override
    public boolean isEmpty() {
        return head.next == head;
    }

    /**
     * 查看线性表是否已满
     *
     * @return 满了返回true 反之false
     */
    @Override
    public boolean isFull() {
        return false;
    }

    /**
     * 返回线性表的第一个元素
     *
     * @return 返回第一个元素
     */
    @Override
    public E getFirst() {
        return head.data;
    }

    /**
     * 返回线性表的最后一个元素
     *
     * @return 返回最后一个的元素
     */
    @Override
    public E getLast() {
        Node<E> temp = head;
        while (temp.next != head){
            temp = temp.next;
        }
        return temp.data;
    }

    /**
     * 删除线性表的第一个元素，并将该值返回
     *
     * 思路：由于开始的约定head节点为第一个节点，在删除第一个节点需把head节点后移一位，遍历到最后的节点并指向head
     * 这个思路一看就不合理，约定头节点的时候有问题
     *
     * @return 返回删除的第一个元素
     */
    @Override
    public E removeFirst() {
        Node<E> temp = head;
        Node<E> cur;
        E e = null;
        if(temp.next == head){ //只剩一个节点的情况
            e = temp.data;
            temp.data = null; //只剩一个节点的时候移除了第一个元素要置空
        }else {
            e = temp.data;
            temp = temp.next;
            cur = temp;
            while (temp.next != head) {
                temp = temp.next;
            }
            temp.next = cur;
            head = cur;
        }
        return e;
    }

    /**
     * 删除线性表的最后一个元素，并将该值返回
     *
     * @return 返回删除的最后一个元素
     */
    @Override
    public E removeLast() {
        Node<E> temp = head;
        E e = null;
        //判断只有头节点的情况
        if(temp.next == head){
            e = temp.data;
            temp.data = null;
        }else {
            //大于一个节点的情况
            while (temp.next.next != head){
                temp = temp.next;
            }
            e = temp.next.data;
            temp.next = head;
        }
        return e;
    }

    /**
     * 将元素插入到线性表的开头位置
     *
     * @param e 将要插入开头的元素
     */
    @Override
    public void addFirst(E e) {

    }

    /**
     * 将元素插入到线性表的末尾位置
     *
     * @param e 将要插入末尾的元素
     */
    @Override
    public void addLast(E e) {

    }

    /**
     * 检查元素是否在线性表中
     *
     * @param e 将要检索的目标元素
     * @return 存在返回true，反之返回false
     */
    @Override
    public boolean contains(E e) {
        return false;
    }

    /**
     * 返回线性表元素的个数
     *
     * @return 返回线性表元素的个数
     */
    @Override
    public int size() {
        return 0;
    }

    /**
     * 将元素插入到线性表的末尾
     *
     * @param e 将要插入的目标元素
     * @return 成功则返回true，失败则返回false
     */
    @Override
    public boolean add(E e) {
        Node<E> temp = head;
        if(temp.data == null){
            temp.data = e;
        }else{

        Node<E> node = new Node<>(head,e);
        while(temp.next != head){
            temp = temp.next;
        }
        temp.next = node;
        }
        return true;
    }

    /**
     * 将第一次出现的元素删除
     *
     * @param e 将要删除的目标元素
     * @return 成功则返回true，失败则返回false
     */
    @Override
    public boolean remove(E e) {
        return false;
    }

    /**
     * 将list中的元素全部添加到线性表末尾
     *
     * @param list 将要添加的目标元素集合
     * @return 成功则返回true，失败则返回false
     */
    @Override
    public boolean addAll(MyList<E> list) {
        return false;
    }

    /**
     * 将list中的元素全部添加到线性表的指定索引位置，位置之后的元素后移
     *
     * @param index 线性表的index位置
     * @param list  将要添加的目标元素集合
     * @return 成功则返回true，失败则返回false
     */
    @Override
    public boolean addAll(int index, MyList<E> list) {
        return false;
    }

    /**
     * 删除线性表中的所有元素
     */
    @Override
    public void clear() {

    }

    /**
     * 返回线性表的index位置的元素
     *
     * @param index 线性表的index位置
     * @return 返回index位置所在元素
     */
    @Override
    public E get(int index) {
        return null;
    }

    /**
     * 以元素e替代线性表index位置的元素，并返回被取代的元素
     *
     * @param index 线性表的index位置
     * @param e     将要插入到index位置的元素
     * @return 返回index位置所在元素
     */
    @Override
    public E set(int index, E e) {
        return null;
    }

    /**
     * 将元素e插入到线性表index位置，其他元素后移
     *
     * @param index 线性表的index位置
     * @param e     将要插入到index位置的元素
     */
    @Override
    public void add(int index, E e) {

    }

    /**
     * 删除线性表中index位置的元素，并返回
     *
     * @param index 线性表的index位置
     * @return 返回指定位置被删除的元素
     */
    @Override
    public E remove(int index) {
        return null;
    }

    /**
     * 返回元素e在线性表中第一次出现的位置，若不存在就返回-1
     *
     * @param e 查询的目标元素
     * @return 若存在返回index，反之返回-1
     */
    @Override
    public int indexOf(E e) {
        return 0;
    }

    /**
     * 返回元素e在线性表中最后一次出现的位置，若不存在就返回-1
     *
     * @param e 查询的目标元素
     * @return 若存在返回index，反之返回-1
     */
    @Override
    public int lastIndexOf(E e) {
        return 0;
    }

    /**
     * 返回被反转的线性表
     *
     * @return 返回一个被反转的线性表
     */
    @Override
    public MyList<E> getReverseList() {
        return null;
    }

    /**
     * 就是一个展示线性表所有的数据
     */
    @Override
    public void show() {
        Node<E> temp = head;
        while (temp.next != head){
            System.out.printf("-"+ temp.data + "-");
            temp = temp.next;
        }
        System.out.printf("-"+ temp.data + "-");  //单循环链表这里经过while循环出来指向链表最后一个结点,怎么能让它在while循环里面指向head呢
        System.out.println();
    }
}
